package com.sky.service.common.Impl;
import com.alibaba.fastjson.JSON;
import com.sky.constant.MessageConstant;
import com.sky.controller.tack.WebSocketServer;
import com.sky.exception.MerchantNotFoundException;
import com.sky.mapper.redis.CourierTradeOrderMapper;
import com.sky.mapper.redis.RedisCourierMapper;
import com.sky.mapper.user.MerchantMapper;
import com.sky.mapper.user.OrderMapper;
import com.sky.pojo.Courier;
import com.sky.pojo.CourierTradeOrder;
import com.sky.pojo.Merchant;
import com.sky.pojo.Orders;
import com.sky.service.common.OrderDispatchService;
import com.sky.utils.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderDispatchServiceImpl implements OrderDispatchService {
    @Resource
    private OrderMapper orderMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CourierTradeOrderMapper courierTradeOrderMapper;
    @Autowired
    private RedisCourierMapper courierMapper;
    /**
     * 查找骑手
     */
    @Override
    public Courier dispatch(Long orderId, Long tradeNo, Long courierId) {
        Orders orders = null;
        //如果是转单，order应该通过tradeNo去获取
        //转单
        if (tradeNo != null) {
            orders = orderMapper.selectOrdersByTradeNo(tradeNo);
        } else {
            orders = orderMapper.getById(orderId);
        }
        //判断订单是否存在
        if (orders == null) {
            throw new MerchantNotFoundException(MessageConstant.ORDER_NOT_FOUND);
        }
        //1.找骑手
        //1.优先查询商家10公里内的在职骑手  -- 多个骑手
        List<Courier> courierList = findCourierNearMerchant(orders.getShopId());
        if (courierId != null) {
            courierList = courierList.stream().filter(courier -> {
                return !Objects.equals(courier.getId(), courierId);
            }).collect(Collectors.toList());
        }
        if (courierId == null || courierList.isEmpty()) {
            return null;
        }
        List<Long> courierIds = courierList.stream().map(Courier::getId).collect(Collectors.toList());
        //2.然后考虑上述骑手中，订单量最少的骑手 -- 找出指定骑手的当日接单量
        String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        //获取指定骑手的当日接单量
        List<Map<String, Long>> mapList = courierTradeOrderMapper.findTodayOrderNumByIds(courierIds, today);
        //找最小值
        Long minNum = mapList.stream().min(Comparator.comparing(map -> {
            return map.get("total");
        })).get().get("total");
        //3.找出最小订单相近的骑手（3单以内）  -- 比如最小订单数是10，那么找出订单量10,11,12,13的骑手   --多个骑手
        courierIds = mapList.stream().filter(map -> {
            return map.get("total") <= minNum + 3;
        }).map(map -> {
            return map.get("id");
        }).collect(Collectors.toList());
        //4.骑手的待接单和已接单（骑手正在进行中的订单）不能超过12
        courierIds = courierTradeOrderMapper.findTodayOrdersLessThen12ByIds(courierIds, today);
//        5.按照上述规则条件如果没有找到，从最初的10公里内的骑手中随机挑选一个
        if (courierIds.isEmpty()) {
            int index = new Random().nextInt(courierIds.size());
            courierIds.add(courierList.get(index).getId());
        }
        //6.然后从所有满足条件的骑手中，找到评分最高的做为最终骑手进行派单
        List<Long> courierIds2 = courierIds;
        //先从10公里内进行提取骑手，按照评分排序降序排列，取第一个。
        Courier finalCourier = courierList.stream().filter(courier -> {
            return courierIds2.contains(courier.getId());
        }).sorted(Comparator.comparing(Courier::getScore).reversed()).collect(Collectors.toList()).get(0);
        //1/2.生成运单，入库
        saveCourierTradeOrder(orders, finalCourier, tradeNo);
        //3.通知骑手 （后面实现）
        notifyCourier(orders.getNumber(), finalCourier.getId());
        return finalCourier;
    }
    @Resource
   private WebSocketServer webSocketServer;
    private void notifyCourier(String number, Long id) {
        Map<String, Object> map = new HashMap<>();
        map.put("tradeNo", number);
        map.put("code", 1);
        map.put("msg", "您有新的待接单，请及时接收！");
        String message = JSON.toJSONString(map);
        //发送
        webSocketServer.sendRiderInfo(message, id);
    }
    @Resource
    private MerchantMapper merchantMapper;
    private void saveCourierTradeOrder(Orders orders, Courier finalCourier, Long tradeNo) {
        //判断是否是转单操作，如果是转单，直接修改运单所对应的courier_id即可
        if(tradeNo!=null){
            //说明是转单操作
            courierTradeOrderMapper.updateCourierIdByTradeNo(finalCourier.getId(),tradeNo);
            return;
        }
        Merchant merchant = merchantMapper.selectById(orders.getShopId());
        //计算提成
        /**
         * - 1 公里内                  3块    取5成
         * - 超出1公里部分 少于3公里部分  3-5   取6成
         * - 超出3公里部分  0.7         >5    取7成
         *    公里数换算成配送费
         */
        double deliveryFee = orders.getDeliveryFee().doubleValue();
        BigDecimal courierCost = null;
        if(deliveryFee<=3){
            courierCost = BigDecimal.valueOf(1.5);
        }else if(deliveryFee>3&&deliveryFee<=5){
            courierCost = BigDecimal.valueOf(1.5);; // 基础费用
            BigDecimal otherCost =BigDecimal.valueOf(deliveryFee-3).multiply(BigDecimal.valueOf(0.6)); //介于3到5块之前，取6成
            courierCost = courierCost.add(otherCost);
        }else if(deliveryFee>5){
            courierCost = BigDecimal.valueOf(1.5);// 基础非
            BigDecimal other1Cost = BigDecimal.valueOf(1.2); //介于1到3公里之间的费用
            BigDecimal endCost = BigDecimal.valueOf(deliveryFee-5).multiply(BigDecimal.valueOf(0.7));
            courierCost = courierCost.add(other1Cost);
            courierCost = courierCost.add(endCost);
        }
        //构建运单对象
        CourierTradeOrder courierTradeOrder = CourierTradeOrder
                .builder()
                .totalAmount(orders.getAmount())
                .courierId(finalCourier.getId())
                .orderNumber(orders.getNumber())
                .waybillStatus(CourierTradeOrder.DISPATCH_OK)
                .tradeCreateTime(LocalDateTime.now())
                .shopAddress(merchant.getShopAddress())
                .remark(orders.getRemark())
                .customerName(orders.getConsignee())
                .customerAddress(orders.getAddress())
                .customerExpectedDeliveryTime(orders.getEstimatedDeliveryTime())
                .shopName(merchant.getShopName())
                .toBeMealTime(orders.getMealTime())
                .telephone(orders.getPhone())
               .income(courierCost)
                .build();

        //保存到数据库
        courierTradeOrderMapper.save(courierTradeOrder);
    }
    /**
     * 查询所有满足条件的骑手(方圆十公里的骑手)
     * @param shopId
     * @return
     */
    private List<Courier> findCourierNearMerchant(Long shopId) {
        Merchant merchant = merchantMapper.selectById(shopId);
        //116.310442,40.056564
        String shopGeo = MapUtils.addressToLnglat(merchant.getShopAddress());
        String[] lnglat = shopGeo.split(",");
        // 以经纬度为中心，获取半径不超过最大距离的所有元素
        Point point = new Point(Double.parseDouble(lnglat[0]),Double.parseDouble(lnglat[1]));
        // 半径为10km
        Distance distance = new Distance(10, RedisGeoCommands.DistanceUnit.KILOMETERS);
        Circle circle = new Circle(point, distance);
        List<Long> courierIds = new ArrayList<>();
        GeoResults<RedisGeoCommands.GeoLocation<Object>> results = redisTemplate.opsForGeo().radius("location2",circle);
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = results.getContent();
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult:content){
            RedisGeoCommands.GeoLocation<Object> geoResultContent = geoResult.getContent();
            System.out.println("名字:"+geoResultContent.getName());
            String idStr = geoResultContent.getName().toString().split("_")[1];
            courierIds.add(Long.parseLong(idStr));
        }
        //根据骑手的id查询骑手信息
        List<Courier> courierList = courierMapper.findCourierByIds(courierIds);
        return courierList;
    }
}
